﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Models;
//using S7.Net;
using HpSocketFunction;
using SerialPortFunction;
using DAL;
using System.Threading;
using System.Diagnostics;
using HslCommunication;
using HslCommunication.Profinet.Siemens;

namespace BLL
{
    #region 单例
    public class LogicSingle
    {
        private static readonly object Lock = new object();
        private static Logic _instance;
        public static Logic Instaince
        {
            get
            {
                if (_instance == null)
                {
                    lock (Lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new Logic();
                        }
                    }
                }
                return _instance;
            }
        }
    }

    #endregion
    public class Logic
    {
        public string SationNo = "325_10";

        #region 通讯对象
        public SiemensS7Net _PLCDevice;//PLC
        public OperateResult _PlcConnect;//PLC连接
        public HpSocketClient _UperComputerClientent;//服务器
        public HpSocketClient _CCDClientent;//CCD
        public HpSocketClient _ScanClient;//扫码抢
        public HpSocketClient _RobotClient;//机器人
        public SerialHelper _HeightDevice;//测高
        public SerialHelper _WeightDevice;//称重
        #endregion

        #region 信息类对象
        public List<DeviceConnMessage> _DeviceConnList; //设备连接信息列表
        public WorkMessage _LocalWorkingMessage;//工作信息
        public PLCWorkAddress _PLCAddress;//PLC地址信息
        public AGVNO _AGVGoodsNO;//AGV物料编号
        #endregion

        #region 功能类对象
        FileOperate _FileClass = new FileOperate();//文件操作类
        AllTypeConnectionHelper _DeciveConnection;//设备初始化连接类
        FirstOperation _FirstOperationClass = new FirstOperation();//首次操作类
        FileOperate _FileOperate = new FileOperate();//文件操作类
        #endregion

        #region 通讯接收类
        UperComputerRecevie _UperComputerRecevie;//上位机客户端接收
        CCDRecevie _CCDrRecevie;//CCD客户端接收
        RobotRecevie _RobotRecevie;//机器人客户端接收
        #endregion

        #region 工作类信息存放对象
        public List<SendWorkOrderInfo> _OrderMessageObj = new List<SendWorkOrderInfo>();//订单对象
        public MESDefaultList _AGVMessageObj;//AGV对象
        public StartInterface _StartMessageObj;//开工对象
        public MESsignal _ReportMessageObj;//报工对象
        #endregion

        #region 控制对象
        public CancellationTokenSource _Token_RunningTask = new CancellationTokenSource();//总循环运行线程状态
        public Thread _RunningTask;//主扫描线程
        public bool RuningState = false;//运行状态手动与自动
        #endregion

        public Logic()
        {
            First();//首次写入
            _DeviceConnList = _FileClass.ReadDriveConnMessage();//读取设备连接信息列表
            _LocalWorkingMessage = _FileClass.ReadWorkMssage();//读取工作信息
            PutWorkObject(); //存入工作对象
            _PLCAddress = _FileClass.ReadPLCAddress();//读取PLC地址信息
            _AGVGoodsNO = _FileClass.ReadAGVGoodsMessage();//读取AGV物料编号
                                                           //LogSingle.Instaince.WriteOrderState(_LocalWorkingMessage.State);

            _DeciveConnection = new AllTypeConnectionHelper(_DeviceConnList);//连接设备准备
            IniDecive();//设备初始化

            ResConnection();//设备重连线程

            _UperComputerRecevie = new UperComputerRecevie(_UperComputerClientent);//上位机客户端接收
            _CCDrRecevie = new CCDRecevie(_CCDClientent);//CCD客户端接收
            _RobotRecevie = new RobotRecevie(_RobotClient);//机器人客户端接收
            RunThread();

        }

        #region 首次写入
        public void First()
        {
            _FirstOperationClass.FirstDecvieWrite();//首次写入设备信息

            _FirstOperationClass.FirstPLCAddressWrite();//首次写入PLC地址

            _FirstOperationClass.FirstWorkMessageWrite();//首次写入工作信息

            _FirstOperationClass.FirstWriteAGVGoodsWrite();//首次写入AGV物料编号
        }
        #endregion

        #region 初始化设备与启动
        public void IniDecive()
        {
            _DeciveConnection.IniSiemensS7_1200(ref _PLCDevice, ref _PlcConnect, "PLC");
            _DeciveConnection.IniTcpClient(ref _UperComputerClientent, "上位机客户端");
            _DeciveConnection.IniTcpClient(ref _CCDClientent, "CCD客户端");
            _DeciveConnection.IniTcpClient(ref _ScanClient, "扫码抢客户端");
            _DeciveConnection.IniTcpClient(ref _RobotClient, "机器人客户端");
            _DeciveConnection.IniCom(ref _WeightDevice, "测重串口");
            _DeciveConnection.IniCom(ref _HeightDevice, "测高串口");
        }
        #endregion

        #region 重连线程
        /// <summary>
        /// 重连线程
        /// </summary>
        public void ResConnection()
        {
            Task ResConnectionTask = new Task(() =>
               {
                   while (!_Token_RunningTask.IsCancellationRequested)
                   {
                       Thread.Sleep(500);
                       IniDecive();
                   }
               });
            ResConnectionTask.Start();
        }
        #endregion

        #region  存入工作对象
        public void PutWorkObject()
        {
            _OrderMessageObj.Add(_LocalWorkingMessage.OrderMessage);//订单
            _AGVMessageObj = _LocalWorkingMessage.AGVMessage;//AGV
            _StartMessageObj = _LocalWorkingMessage.StartMessage;//开工
            _ReportMessageObj = _LocalWorkingMessage.ReportMessage;//报工
            this.SationNo = _LocalWorkingMessage.SationNo;//工位号
        }
        #endregion

        #region 发送计时对象
        Stopwatch _AGV1WatchTime = new Stopwatch();//AGV1发送延时计算
        Stopwatch _AGV2WatchTime = new Stopwatch();//AGV2发送延时计算
        Stopwatch _StartWorkWatchTime = new Stopwatch();//开工发送延时计算
        Stopwatch _ReportWorkWatchTime = new Stopwatch();//开工发送延时计算
        Stopwatch _AllowNextStationWatchTime = new Stopwatch();//允许一个工位延时计算
        #endregion

        #region  运行线程
        public void RunThread()
        {
            _RunningTask = new Thread(() =>
            {
                while (!_Token_RunningTask.IsCancellationRequested)
                {
                    if (!RuningState)
                    {
                        continue;
                    }
                    Thread.Sleep(10);
                    //LogSingle.Instaince.WriteMainLog("线程启动");

                    #region AGV信号
                    if (_PlcConnect.IsSuccess)
                    {
                        WorkInteraction(_PLCAddress.CallAGV1, "AGV1State", _AGV1WatchTime, "AGV1", "Up");
                        WorkInteraction(_PLCAddress.CallAGV2, "AGV2State", _AGV1WatchTime, "AGV2", "Up");
                        WorkInteraction(_PLCAddress.CallAGV1, "AGV1State", _AGV1WatchTime, "AGV1", "Down");
                        WorkInteraction(_PLCAddress.CallAGV2, "AGV2State", _AGV1WatchTime, "AGV2", "Down");
                    }
                    #endregion

                    #region CCD开工信号
                    if (_CCDrRecevie.CCDRecevieIO["Fetch"].Length > 0)
                    {
                        if (_StartWorkWatchTime.ElapsedMilliseconds > 10000 || _StartWorkWatchTime.ElapsedMilliseconds == 0)
                        {
                            _StartMessageObj.CatchPlaceNo[0] = _CCDrRecevie.CCDRecevieIO["Fetch"];
                            _ReportMessageObj.CatchPlaceNo[0] = _CCDrRecevie.CCDRecevieIO["Fetch"];

                            _StartWorkWatchTime.Start();
                            if (StartWork())//发送开工
                            {
                                _CCDrRecevie.CCDRecevieIO["Fetch"] = "";
                            }
                            _StartWorkWatchTime.Reset();
                        }
                    }
                    else
                    {
                        _StartWorkWatchTime.Stop();
                        _StartWorkWatchTime.Reset();
                    }
                    #endregion

                    #region 机器人开工信号
                    if (_RobotRecevie.RobotRecevieIO["Fetch"].Length > 0)
                    {
                        if (_StartWorkWatchTime.ElapsedMilliseconds > 10000 || _StartWorkWatchTime.ElapsedMilliseconds == 0)
                        {
                            _StartMessageObj.CatchPlaceNo[0] = _RobotRecevie.RobotRecevieIO["Fetch"];

                            string JsonMessage = JsonHelper.EntityToStr(_StartMessageObj);//转换Json
                            _StartWorkWatchTime.Start();
                            if (_UperComputerClientent.SendData("StartWork" + "," + JsonMessage))//发送开工
                            {
                                _RobotRecevie.RobotRecevieIO["Fetch"] = "";
                            }
                            _StartWorkWatchTime.Reset();
                        }
                    }
                    else
                    {
                        _StartWorkWatchTime.Stop();
                        _StartWorkWatchTime.Reset();
                    }
                    #endregion

                    #region PLC报工信号
                    if (_PlcConnect.IsSuccess && _PLCDevice.ReadBool(_PLCAddress.ReportWork).Content)
                    {
                        if (_ReportWorkWatchTime.ElapsedMilliseconds > 10000 || _ReportWorkWatchTime.ElapsedMilliseconds == 0)
                        {
                            _ReportMessageObj.TargetPlaceNo = _CCDrRecevie.CCDRecevieIO["Put"];

                            _ReportWorkWatchTime.Start();
                            if (ReportWork())//发送报工
                            {
                                _PLCDevice.Write(_PLCAddress.ReportWork, false);
                                _CCDrRecevie.CCDRecevieIO["Put"] = "";
                            }
                            _ReportWorkWatchTime.Reset();
                        }
                    }
                    else
                    {
                        _ReportWorkWatchTime.Stop();
                        _ReportWorkWatchTime.Reset();
                    }
                    #endregion

                    #region PLC允许下个工位
                    if (_PlcConnect.IsSuccess && _PLCDevice.ReadBool(_PLCAddress.AllowNextStation).Content)
                    {
                        if (_AllowNextStationWatchTime.ElapsedMilliseconds > 10000 || _AllowNextStationWatchTime.ElapsedMilliseconds == 0)
                        {
                            _AllowNextStationWatchTime.Start();
                            SendWorkOrderInfo NextStationOrderInfo = _OrderMessageObj[0];
                            if (!(_OrderMessageObj[0].Quantity == 0))
                            {
                                NextStationOrderInfo.Quantity = 2;
                            }
                            else
                            {
                                NextStationOrderInfo.Quantity = 1;
                            }
                            NextStationOrderInfo.StationNo = "325_15";
                            string JsonMessage = JsonHelper.EntityToStr(NextStationOrderInfo);//转换Json
                            if (_UperComputerClientent.SendData("StationEnd" + "," + JsonMessage))//发送成功
                            {
                                _PLCDevice.Write(_PLCAddress.AllowNextStation, false);
                            }
                            _AllowNextStationWatchTime.Reset();
                        }
                    }
                    else
                    {
                        _AllowNextStationWatchTime.Stop();
                        _AllowNextStationWatchTime.Reset();
                    }

                    #endregion

                    #region 开工反馈
                    if (_UperComputerRecevie.UperComputerRecevieIO["StartWorkState"].Length > 0)
                    {
                        if (_UperComputerRecevie.UperComputerRecevieIO["StartWorkState"] == "1")//开工成功
                        {
                            LogSingle.Instaince.WriteOrderState(0);//写入订单窗体状态
                            _LocalWorkingMessage.State = 0;
                            _PLCDevice.Write(_PLCAddress.StartWorkState, 1);//写入plc开工反馈
                        }
                        else if (_UperComputerRecevie.UperComputerRecevieIO["StartWorkState"] == "2")//开工失败
                        {
                            LogSingle.Instaince.WriteOrderState(1);//写入订单窗体状态
                            _LocalWorkingMessage.State = 1;
                            _PLCDevice.Write(_PLCAddress.StartWorkState, 2);//写入plc开工反馈
                        }
                        _UperComputerRecevie.UperComputerRecevieIO["StartWorkState"] = "";
                    }
                    #endregion

                    #region 报工反馈
                    if (_UperComputerRecevie.UperComputerRecevieIO["ReportWorkState"].Length > 0)
                    {
                        if (_UperComputerRecevie.UperComputerRecevieIO["ReportWorkState"] == "1")//报工成功
                        {
                            LogSingle.Instaince.WriteOrderState(0);//写入订单窗体状态
                            _LocalWorkingMessage.State = 0;
                            _PLCDevice.Write(_PLCAddress.ReportWorkState, 1);//写入plc报工反馈
                            _OrderMessageObj[0].Quantity = _OrderMessageObj[0].Quantity - 1;
                            if (_OrderMessageObj[0].Quantity <= 0)
                            {
                                _OrderMessageObj[0].Quantity = 0;
                                //发送订单完成...
                                _UperComputerClientent.SendData("OrderEnd" + SationNo);
                            }
                        }
                        else if (_UperComputerRecevie.UperComputerRecevieIO["ReportWorkState"] == "2")//报工失败
                        {
                            LogSingle.Instaince.WriteOrderState(2);//写入订单窗体状态
                            _LocalWorkingMessage.State = 2;
                            _PLCDevice.Write(_PLCAddress.ReportWorkState, 2);//写入plc报工反馈
                        }
                        _UperComputerRecevie.UperComputerRecevieIO["ReportWorkState"] = "";
                    }

                    #endregion

                    #region 接收服务器订单给PLC
                    if (_UperComputerRecevie.UperComputerRecevieIO["Order"].Length > 0)
                    {
                        _OrderMessageObj[0] = JsonHelper.StrToEntity<SendWorkOrderInfo>(_UperComputerRecevie.UperComputerRecevieIO["Order"]);
                        _PLCDevice.Write(_PLCAddress.OrderNum, _OrderMessageObj[0].Quantity);//给PLC订单数量
                        IniWorkMessage();//工作信息初始化
                        _UperComputerRecevie.UperComputerRecevieIO["Order"] = "";
                    }
                    #endregion
                }
            });
            _RunningTask.Start();
        }
        #endregion

        #region AGV调度判断
        public void WorkInteraction(string PLCAddress, string UperComputerRecevieIO, Stopwatch WatchTime, string Flag, string Mode)
        {
            if (_PLCDevice.ReadBool(PLCAddress).Content)
            {
                if (WatchTime.ElapsedMilliseconds > 10000 || WatchTime.ElapsedMilliseconds == 0)
                {
                    WatchTime.Start();
                    if (DispatchAGV(Flag, Mode))//发送调度AGV
                    {
                        WatchTime.Stop();
                    }
                    WatchTime.Reset();
                }
                if (_UperComputerRecevie.UperComputerRecevieIO[UperComputerRecevieIO] == "1")
                {
                    _PLCDevice.Write(PLCAddress, false);
                    _UperComputerRecevie.UperComputerRecevieIO[UperComputerRecevieIO] = "0";
                }
            }
            else
            {
                WatchTime.Stop();
                WatchTime.Reset();
            }
        }
        #endregion

        #region 工作信息初始化
        public void IniWorkMessage()
        {
            _StartMessageObj.WorkOrderNo = "";
            _StartMessageObj.SerialNo = "";
            _StartMessageObj.CatchPlaceNo = new string[] { };
            _StartMessageObj.SerialNo = "";
            _StartMessageObj.StationNo = "";

            _ReportMessageObj.WorkOrderNo = "";
            _ReportMessageObj.SerialNo = "";
            _ReportMessageObj.ManufacturingItems = new List<KeyValueInfo>();
            _ReportMessageObj.GoodQty = "";
            _ReportMessageObj.BadQty = "";
            _ReportMessageObj.CatchData = new List<Catch>();
            _ReportMessageObj.CatchPlaceNo = new string[] { };
            _ReportMessageObj.InspectionItems = new List<KeyValueInfo>();
        }
        #endregion

        #region PLC交互
        /// <summary>
        /// PLC软件交互
        /// </summary>
        public void SendMessageToPlc(string IOAdress, PLCDataType type, object Value)
        {

            if (_PlcConnect.IsSuccess)
            {
                S71200Helper.S7Write(_PLCDevice, IOAdress, Value, type);
            }
        }

        public object ReadMessageToPlc(string IOAdress, PLCDataType type)
        {
            object res = null;
            if (_PlcConnect.IsSuccess)
            {
                res = S71200Helper.S7Read(_PLCDevice, IOAdress, type);
            }
            return res;
        }
        #endregion

        #region 保存信息
        public void SaveImage()
        {
            _LocalWorkingMessage.OrderMessage = _OrderMessageObj[0];
            _LocalWorkingMessage.AGVMessage = _AGVMessageObj;
            _LocalWorkingMessage.StartMessage = _StartMessageObj;
            _LocalWorkingMessage.ReportMessage = _ReportMessageObj;
            _LocalWorkingMessage.SationNo = this.SationNo;
            _FileOperate.WriteWorkMssage(_LocalWorkingMessage);//写入工作信息
            _FileOperate.WriteDriveConnMessage(_DeviceConnList);//写入设备信息
        }
        #endregion

        #region AGV调度
        public bool DispatchAGV(string Flag, string Mode)
        {
            if (_OrderMessageObj[0].MaterialCodification == "202")//202产品
            {
                if (Flag == "AGV1")
                {
                    if (Mode == "Up")
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV1_202TagUp;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV1_202Up;
                    }
                    else
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV1_202TagDown;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV1_202Down;
                    }
                }
                else if (Flag == "AGV2")
                {
                    if (Mode == "Up")
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV2_202TagUp;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV2_202Up;
                    }
                    else
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV2_202TagDown;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV2_202Down;
                    }
                }
            }
            else if (_OrderMessageObj[0].MaterialCodification == "501")//501产品
            {
                if (Flag == "AGV1")
                {
                    if (Mode == "Up")
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV1_501TagUp;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV1_501Up;
                    }
                    else
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV1_501TagDown;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV1_501Down;
                    }
                }
                else if (Flag == "AGV2")
                {
                    if (Mode == "Up")
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV2_501TagUp;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV2_501Up;
                    }
                    else
                    {
                        _AGVMessageObj.Tag = _AGVGoodsNO.AGV1_501TagDown;
                        _AGVMessageObj.SupplyMaterialCodifications = _AGVGoodsNO.AGV2_501Down;

                    }
                }
            }
            string JsonMessage = JsonHelper.EntityToStr(_AGVMessageObj);//转换Json
            return _UperComputerClientent.SendData("AGV" + "," + JsonMessage);
        }
        #endregion

        #region 开工
        public bool StartWork()
        {
            string JsonMessage = JsonHelper.EntityToStr(_StartMessageObj);//转换Json
            return _UperComputerClientent.SendData("StartWork" + "," + JsonMessage);
        }
        #endregion

        #region 报工
        public bool ReportWork()
        {
            string JsonMessage = JsonHelper.EntityToStr(_ReportMessageObj);
            return _UperComputerClientent.SendData("ReportWork" + "," + JsonMessage);
        }
        #endregion
    }
}
